﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq;
using VAdvantage.UIEvent;
using VAdvantage.Grids;
using VAdvantage.Model;
using VAdvantage.Editor;
using VAdvantage.Logging;
using System.Collections.Generic;
using VAdvantage.Classes;
using VAdvantage.Utility;
using System.Threading;
using System.ComponentModel;
using System.Windows.Data;
using System.Windows.Controls.Primitives;
using System.Collections.ObjectModel;
using System.Collections;
using System.Data;
using VAdvantage.DataBase;



namespace VAdvantage.Controls
{
    public class VComboBox : System.Windows.Controls.ComboBox, IControl, IContextMenuListener
    {
        public VComboBox()
        {

            this.Style = App.Current.Resources["VComboboxStyle"] as Style;

            this.Loaded += new RoutedEventHandler(ComboBox_Loaded);
            this.SelectionChanged += new SelectionChangedEventHandler(ComboBox_SelectionChanged);

        }

        #region Abstract Level

        void ComboBox_Loaded(object sender, RoutedEventArgs e)
        {
            SetSelectionFromValue();
        }

        private object _Selection;

        void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count > 0)
            {
                _Selection = e.AddedItems[0];
                SelectedValue = GetMemberValue(_Selection);
            }
            else
            {
                _Selection = null;
                SelectedValue = null;
            }
            SetColor();
            if (VetoableChangeListener != null  && ((_raiseEvent && IsDropDownOpen) || _isDeleteKeydown))
            {
                VetoableChangeListener(this, Event.Empty);
            }
        }

        private object GetMemberValue(object item)
        {
            if (!String.IsNullOrEmpty(ValueMemberPath))
            {
                return item.GetType().GetProperty(ValueMemberPath).GetValue(item, null);
            }
            return null;
        }

        public static readonly DependencyProperty ValueMemberPathProperty =
          DependencyProperty.Register("ValueMemberPath", typeof(string), typeof(VAdvantage.Controls.VComboBox), null);

        public string ValueMemberPath
        {
            get
            {
                return ((string)(base.GetValue(VComboBox.ValueMemberPathProperty)));
            }
            set
            {
                base.SetValue(VComboBox.ValueMemberPathProperty, value);
            }
        }

        public static readonly DependencyProperty SelectedValueProperty =
          DependencyProperty.Register("SelectedValue", typeof(object), typeof(VAdvantage.Controls.VComboBox),
          new PropertyMetadata((o, e) =>
          {
              ((VComboBox)o).SetSelectionFromValue();
          }));

        public object SelectedValue
        {
            get
            {
                return ((object)(base.GetValue(VComboBox.SelectedValueProperty)));
            }
            set
            {
                base.SetValue(VComboBox.SelectedValueProperty, value);
            }
        }


        private void SetSelectionFromValue()
        {
            var value = SelectedValue;
            if (Items.Count > 0 && value != null)
            {
                var sel = (from item in Items
                           where  GetMemberValue(item).Equals(value)
                           select item).SingleOrDefault();
                if (sel == null && value is string)
                {
                    //int value in form of string like ["1000078"]
                    // user can  create 'Table' type column but not add suffix ['_ID'] to name of column
                    //In this case dataSource of combobox contain INT types and combo's value is STRING type
                    int number;
                    if (int.TryParse((string)value, out number))
                    {
                      sel =   (from item in Items
                         where GetMemberValue(item).Equals(number)
                         select item).SingleOrDefault();
                    }
                }
                _Selection = sel;
                SelectedItem = sel;
            }

            if (_field == null)
            {
                return;
            }

            if (value != null && _Selection == null)// && _raiseEvent)
            {
                if (value is int && Convert.ToInt32(value) < 0)
                {
                    return;
                }
                SetValue1(value);
            }
            else if (value == null && this.SelectedIndex > -1) //_raiseEvent && 
            {
                this.SelectedIndex = -1;
                _Selection = null;
            }
        }

        KeyNamePair kp = new KeyNamePair(-1, " ");
        ObservableCollection<KeyNamePair> lst = new ObservableCollection<KeyNamePair>();

        public void SetValue1(object value)
        {
            _inserting = _field.IsInserting();
            //if (_inserting)
            //{
            //    string f = "ss";

            //}
            _raiseEvent = false;

            if (value == null || value.ToString() == "" || (value is int && Convert.ToInt32(value) < 0))
            {
                //this.SelectedIndex = 0;
                this.SelectedIndex = -1;
                _lastDisplay = "";
                _raiseEvent = true;
                return;
            }

            if (_lookup == null)
            {
                //this.Items.Clear();
                this.SelectedItem = null;
                //this.DisplayMember = "";
                //this.ValueMember = "";
                kp.SetName(value.ToString());

                this.ItemsSource = lst;
                _Selection = lst[0]; ;
                SelectedItem = lst[0];

                this.SelectedIndex = 0;
                //this.Text = value.ToString();
                _lastDisplay = value.ToString();
                _raiseEvent = true;
                return;
            }



            //this.SelectedValue = value;

            //if (this.SelectedValue == null)
            //{
            //    try
            //    {
            //        this.SelectedValue = Convert.ToInt32(value);
            //    }
            //    catch
            //    {
            //    }
            //}





            if (_lookup.IsValidated())
            {
                NamePair pp = null;
                bool notFound = false;

                pp = _lookup.GetFromValidatedList(value);

                if (pp != null)
                {
                    //Check this.datasource has value

                    IList _data = (IList)this.ItemsSource;

                    if (!_data.Contains(pp))
                    {
                        try
                        {
                            this.SelectedItem = null;
                            NamePair[] _dataSet = new NamePair[_data.Count + 1];
                            _data.CopyTo(_dataSet, 0);
                            _dataSet[_data.Count] = pp;
                            SetDataSource(_dataSet);
                            BindValue = _columnName.ToUpper();
                            _dataSet = null;
                            _data = null;
                            //this.SelectedItem = pp;
                            //this.SelectedIndex = _data.Count - 1;
                        }
                        catch
                        {

                        }
                    }
                    this.SelectedValue = value;

                }
                else
                {
                    worker2 = new BackgroundWorker();
                    worker2.WorkerSupportsCancellation = true;
                    worker2.DoWork += (sender, e) =>
                       {
                           if (worker2.CancellationPending)
                           {
                               e.Cancel = true;
                               return;
                           }
                           _lastDisplay = _lookup.GetDisplay(value);
                           if (_lastDisplay.Equals("<-1>"))
                           {
                               _lastDisplay = "";
                               _Selection = null;
                           }

                           notFound = _lastDisplay.StartsWith("<") && _lastDisplay.EndsWith(">");
                           while (worker != null && worker.IsBusy)
                           {
                               if (worker.CancellationPending || worker2.CancellationPending)
                               {
                                   e.Cancel = true;
                                   return;
                               }
                           }
                           //if (notFound)
                           //{
                           //    _lookup.Refresh();

                           //}

                           pp = _lookup.Get(value);
                           //           //wait

                       };
                    worker2.RunWorkerCompleted += (sender, e) =>
                        {
                            if (notFound)
                            {
                                //this.SelectedItem = null;

                                if (value.Equals(0))
                                {
                                    _lookup._data.Add(new KeyNamePair(0, ""));
                                }
                                // SetDataSource(_lookup._data);
                                //BindValue = _columnName.ToUpper();

                                this.SelectedValue = null;
                                //this.SelectedValue = value;
                            }

                            if (notFound)	//	<key>
                            {
                                //_Selection = null;
                                //actionCombo(null);             //  data binding
                                // log.Fine(_columnName + "=" + value + ": Not found - " + _lastDisplay);
                                //  log.Fine(_columnName + "=" + value + ": Not found");
                            }
                            //  we have lookup
                            else if (this.SelectedItem == null)
                            {

                                if (pp != null)
                                {
                                    // log.Info(_columnName + " added to combo - " + pp);
                                    //  Add to Combo
                                    try
                                    {
                                        this.SelectedItem = null;
                                        IList _data = (IList)this.ItemsSource;
                                        NamePair[] _dataSet = new NamePair[_data.Count + 1];
                                        _data.CopyTo(_dataSet, 0);

                                        if (!_dataSet.Contains(pp))
                                        {

                                            _dataSet[_data.Count] = pp;
                                            SetDataSource(_dataSet);
                                            BindValue = _columnName.ToUpper();
                                            _dataSet = null;
                                            _data = null;
                                        }
                                        //this.SelectedItem = pp;
                                        //this.SelectedIndex = _data.Count - 1;
                                    }
                                    catch
                                    {

                                    }
                                    this.SelectedValue = value;
                                    //this.SelectedItem = pp;
                                    //m_combo.setValue(value);
                                }
                            }
                            //  Not in Lookup - set to Null
                            if (this.SelectedValue == null)
                            {
                                // log.Info(_columnName + "=" + value + ": not in Lookup - set to NULL");
                                //actionCombo(null);             //  data binding (calls setValue again)
                                // _value = null;
                            }
                            _inserting = false;
                            _raiseEvent = true;
                        };
                    worker2.RunWorkerAsync();
                }

            }
            else if (!_lookup.IsValidated())
            {
                _lastDisplay = _lookup.GetDisplayFromList(value);
                if (_lastDisplay.Equals("<-1>"))
                {
                    _lastDisplay = "";
                    _Selection = null;
                }
                bool notFound = _lastDisplay.StartsWith("<") && _lastDisplay.EndsWith(">");
                if (!notFound)
                {
                    IList _data = new ObservableCollection<NamePair>();

                    if (value is string)
                    {
                        _data.Add(new ValueNamePair(value.ToString(), _lastDisplay));
                    }
                    else
                    {
                        _data.Add(new KeyNamePair((int)value, _lastDisplay));
                    }
                    this.ItemsSource = _data;
                    //this.DisplayMember = "Name";
                    //this.ValueMember = "Key";
                    BindValue = _columnName.ToUpper();
                    this.SelectedIndex = 0;
                    _inserting = false;
                    _raiseEvent = true;
                }
                else
                {
                    ThreadPool.QueueUserWorkItem(delegate
                    {
                        // _lookup.Refresh();
                        NamePair pp = _lookup.Get(value);
                        if (pp != null)
                        {
                            Dispatcher.BeginInvoke(delegate
                            {
                                if (pp != null)
                                {
                                    List<NamePair> _data = new List<NamePair>();

                                    if (value is string)
                                    {
                                        _data.Add(new ValueNamePair(value.ToString(), pp.GetName()));
                                    }
                                    else
                                    {
                                        _data.Add(new KeyNamePair((int)value, pp.GetName()));
                                    }
                                    this.ItemsSource = _data;
                                    //this.DisplayMember = "Name";
                                    //this.ValueMember = "Key";
                                    BindValue = _columnName.ToUpper();
                                    this.SelectedIndex = 0;
                                    _inserting = false;
                                    _raiseEvent = true;
                                }
                            });
                        }
                    });
                }
            }



            //       _lastDisplay = _lookup.GetDisplay(value);
            //       if (_lastDisplay.Equals("<-1>"))
            //       {
            //           _lastDisplay = "";
            //           _Selection = null;
            //           SelectedItem = null;
            //       }
            //       notFound = _lastDisplay.StartsWith("<") && _lastDisplay.EndsWith(">");
            //       if (notFound && _lookup.IsValidated())
            //       {
            //           _lookup.Refresh();
            //           pp = _lookup.Get(value);
            //           _lastDisplay = _lookup.GetDisplay(value);
            //       }

            //   };


            //worker2.RunWorkerCompleted += (sender, e) =>
            //{
            //    if (worker2.CancellationPending && e.Cancelled)
            //    {
            //        if (e.Cancelled)
            //        {
            //            worker2 = null;
            //            return;
            //        }
            //    }

            //    if (notFound)
            //    {
            //        log.Info(_columnName + "=" + value + ": Not found - " + _lastDisplay);
            //        //    //  we may have a new value
            //        SetDataSource(_lookup._data);
            //        BindValue = this._columnName.ToUpper();
            //        this.SelectedValue = value;
            //        //    notFound = _lastDisplay.StartsWith("<") && _lastDisplay.EndsWith(">");
            //    }
            //    if (notFound)	//	<key>
            //    {
            //        _Selection = null;
            //        //actionCombo(null);             //  data binding
            //        log.Fine(_columnName + "=" + value + ": Not found - " + _lastDisplay);
            //        //  log.Fine(_columnName + "=" + value + ": Not found");
            //    }
            //    //  we have lookup
            //    else if (this.SelectedItem == null)
            //    {
            //        if (pp != null)
            //        {
            //            //    log.Info(_columnName + " added to combo - " + pp);
            //            //    //  Add to Combo
            //            try
            //            {
            //                //IList _data = (IList)this.ItemsSource
            //                ((IList)this.ItemsSource).Add(pp);
            //            }
            //            catch
            //            {

            //            }

            //            this.SelectedItem = pp;
            //            _Selection = this.SelectedItem;
            //            //    //m_combo.setValue(value);

            //        }
            //    }
            //    //  Not in Lookup - set to Null
            //    if (this.SelectedItem == null)
            //    {
            //    //    log.Info(_columnName + "=" + value + ": not in Lookup - set to NULL");
            //    //    //actionCombo(null);             //  data binding (calls setValue again)
            //        SelectedValue = null;
            //        _Selection = null;
            //    }


            //    if (this.SelectedItem == null && (!_lookup.IsValidated()))
            //    {
            //        if (!notFound)
            //        {
            //            IList _data = new ObservableCollection<NamePair>();

            //            if (value is string)
            //            {
            //                _data.Add(new ValueNamePair(value.ToString(), _lastDisplay));
            //            }
            //            else
            //            {
            //                _data.Add(new KeyNamePair((int)value, _lastDisplay));
            //            }
            //            this.ItemsSource = _data;
            //             BindValue = this._columnName.ToUpper();
            //            //this.DisplayMember = "Name";
            //            //this.ValueMember = "Key";
            //            this.SelectedIndex = 0;

            //        }
            //    }
            //    // this.SelectionStart = this.Text.Length;
            //    _inserting = false;
            //    _raiseEvent = true;
            //    worker2 = null;
            //};
            //worker2.RunWorkerAsync();

        }


        protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs
            e)
        {

            base.OnItemsChanged(e);
            SetSelectionFromValue();
        }


        private bool _isDeleteKeydown = false;
        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            if (e.Key == Key.Delete)
            {
                if (this.SelectedIndex != -1 || this.SelectedItem != null)
                {
                    _isDeleteKeydown = true;
                    this.SelectedIndex = -1;
                    _isDeleteKeydown = false;
                }
            }
        }



        #endregion

        #region Constructor

        /// <summary>
        /// Parametrised Constructor
        /// </summary>
        /// <param name="columnName">Displayed column name</param>
        /// <param name="mandatory">Bool Type(mendatory status)</param>
        /// <param name="isReadOnly">Bool Type(readonly status)</param>
        /// <param name="isUpdateable">Bool type(is update able)</param>
        /// <param name="lookup">selected data as key pair</param>
        public VComboBox(String columnName, bool mandatory, bool isReadOnly, bool isUpdateable, Lookup lookup, int displayLength)
            : this()
        {
            ctx = Utility.Envs.GetContext();
            // log = VLogger.GetVLogger(typeof(VComboBox).FullName);
            //set the property of control that auto suggest text
            //this.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
            // this.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
            //this.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            //this.DropDownHeight = 1;
            //this.ResizeRedraw = false;

            //set control name as column name 
            //this.Name = columnName;
            _columnName = columnName;
            //mendatory fileds
            _mandatory = mandatory;
            //set lookup class obj.
            _lookup = lookup;

            //this.Width = (displayLength > 30) ? 500 : 300;
            //
            //CommonFunctions.SetCmboBoxPrperties(this);

            // set contextmenu of combobox
            //this.ContextMenuStrip = popupMenu;

            //	*** VComboBox	***
            if (_lookup != null && _lookup.IsValidated())	//	No Search
            {

                //worker = new BackgroundWorker();
                //worker.WorkerSupportsCancellation = true;
                //worker.DoWork += (sender, e) =>
                //    {
                //        if (worker.CancellationPending)
                //        {
                //            e.Cancel = true;
                //            return;
                //        }

                //       try
                //        {
                _lookup.FillComboBox(_mandatory, false, false, false);



                SetDataSource(_lookup._data);
                //    }
                //    catch
                //    {
                //        if (worker.CancellationPending)
                //        {
                //            e.Cancel = true;
                //        }
                //    }
                //};

                //worker.RunWorkerCompleted += (sender, e) =>
                //    {
                //        if (e.Cancelled)
                //        {
                //            worker = null;
                //            return;
                //        }
                //        try
                //        {
                //           SetDataSource(_lookup._data);
                //        }
                //        catch
                //        {
                //        }
                //        worker = null;
                //    };

                //worker.RunWorkerAsync();

                //this.DataSource = _lookup.GetLookupDataTable(columnName);// .GetListDatasource();

                //this.DisplayMember = columnName + "_d";//"Name";//
                //this.ValueMember = columnName;//"Key";// 
                this.DisplayMemberPath = "Name";// columnName + "_d";

                //this.SelectedValuePath = "Key";

                this.ValueMemberPath = "Key";// columnName;

            }

            else if (lookup != null && !lookup.IsValidated())
            {
                //lookup.FillDirectList();
                this.DisplayMemberPath = "Name";// columnName + "_d";
                //this.SelectedValuePath = "Key";// columnName;
                this.ValueMemberPath = "Key";
            }
            else
            {
                this.DisplayMemberPath = "Name";// columnName + "_d";
                //this.SelectedValuePath = "Key";// columnName;
                this.ValueMemberPath = "Key";
            }

            //this.Enter += new EventHandler(VComboBox_Enter);

            //ReadWrite	-	decides what components to show
            if (isReadOnly || !isUpdateable || _lookup == null)
                SetReadOnly(true);//this.Enabled = false; //
            else
                SetReadOnly(false); //this.Enabled = true; //

            SetPopup();
            //	VBPartner quick entry link
            //if (columnName.Equals("C_BPartner_ID"))
            //{
            //    bpartnerNewItem = new ToolStripMenuItem(Common.GetMessage.GetMessageText("New", true), Properties.Resources.Zoom);
            //    //bpartnerNewItem.Click += new EventHandler(bpartnerNew_Click);
            //    popupMenu.Items.Add(bpartnerNewItem);
            //    bpartnerUpdateItem = new ToolStripMenuItem(Common.GetMessage.GetMessageText("Update", true), Properties.Resources.Zoom);
            //    //bpartnerUpdateItem.Click += new EventHandler(bpartnerUpdate_Click);
            //    popupMenu.Items.Add(bpartnerUpdateItem);
            //}
            //else
            //{
            //    if (_lookup != null && _lookup.GetZoomWindow() == 0)
            //        zoomItem.Enabled = false;
            //}
            //this.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.Never;
            lst.Add(kp);

            //this.SelectionChanged += OnSelectionChanged;

            child.Height = 40;
            child.Width = 40;

        }

        void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            //if (VetoableChangeListener != null && _raiseEvent)
            //{
            //    VetoableChangeListener(this, EventArgs.Empty);
            //}
        }

        private void SetDataSource(List<NamePair> list)
        {
            try
            {

                if (_dataSource != null)
                {
                    _dataSource.Clear();
                    _dataSource = null;
                }

                NamePair[] p = new NamePair[list.Count];
                p = list.ToArray();

                _dataSource = p.ToList();


                this.ItemsSource = _dataSource;
            }
            catch
            {
                //return _dataSource;
            }
        }


        private void SetDataSource(NamePair[] list)
        {
            try
            {

                if (_dataSource != null)
                {
                    _dataSource.Clear();
                    _dataSource = null;
                }

                _dataSource = list.ToList();


                this.ItemsSource = _dataSource;
                list = null;
            }
            catch
            {
                //return _dataSource;
            }
        }

        /// <summary>
        /// Set Parameters in the combo places in design time
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="mandatory"></param>
        /// <param name="isReadOnly"></param>
        /// <param name="isUpdateable"></param>
        /// <param name="lookup"></param>
        /// <param name="displayLength"></param>
        public void SetParameter(String columnName, bool mandatory, bool isReadOnly, bool isUpdateable, Lookup lookup, int displayLength)
        {
            ctx = Utility.Envs.GetContext();
            log = VLogger.GetVLogger(typeof(VComboBox).FullName);
            //set the property of control that auto suggest text
            // this.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.Suggest;
            // this.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems;
            //this.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            //this.DropDownHeight = 1;
            //this.ResizeRedraw = false;

            //set control name as column name 
            this.Name = columnName;
            //_columnName = columnName;
            //mendatory fileds
            _mandatory = mandatory;
            //set lookup class obj.
            _lookup = lookup;

            this.Width = (displayLength > 30) ? 500 : 300;
            //
            //CommonFunctions.SetCmboBoxPrperties(this);

            // set contextmenu of combobox
            //this.ContextMenuStrip = popupMenu;

            //	*** VComboBox	***
            if (_lookup != null && _lookup.IsValidated())	//	No Search
            {

                _lookup.FillComboBox(_mandatory, false, false, false);

                //this.DataSource = _lookup.GetLookupDataTable(columnName);// .GetListDatasource();

                SetDataSource(_lookup._data);


                //this.DisplayMember = columnName + "_d";//"Name";//
                //this.ValueMember = columnName;//"Key";// 
                this.DisplayMemberPath = "Name";// columnName + "_d";
                // this .ValueMemberPath = "Key";// columnName;
                this.SelectedValuePath = "Key";

            }
            else
            {
                this.DisplayMemberPath = "Name";// columnName + "_d";
                //this.ValueMemberPath = "Key";// columnName;
                this.SelectedValuePath = "Key";
            }

            //this.Enter += new EventHandler(VComboBox_Enter);

            //ReadWrite	-	decides what components to show
            if (isReadOnly || !isUpdateable || _lookup == null)
                SetReadOnly(true);//this.Enabled = false; //
            else
                SetReadOnly(false); //this.Enabled = true; //

            SetPopup();
            //	VBPartner quick entry link
            //if (columnName.Equals("C_BPartner_ID"))
            //{
            //    bpartnerNewItem = new ToolStripMenuItem(Common.GetMessage.GetMessageText("New", true), Properties.Resources.Zoom);
            //    //bpartnerNewItem.Click += new EventHandler(bpartnerNew_Click);
            //    popupMenu.Items.Add(bpartnerNewItem);
            //    bpartnerUpdateItem = new ToolStripMenuItem(Common.GetMessage.GetMessageText("Update", true), Properties.Resources.Zoom);
            //    //bpartnerUpdateItem.Click += new EventHandler(bpartnerUpdate_Click);
            //    popupMenu.Items.Add(bpartnerUpdateItem);
            //}
            //else
            //{
            //    if (_lookup != null && _lookup.GetZoomWindow() == 0)
            //        zoomItem.Enabled = false;
            //}
            // this.DataBindings.DefaultDataSourceUpdateMode = DataSourceUpdateMode.Never;
            // lst.Add(kp);
        }


        /// <summary>
        /// parameterized const
        /// </summary>
        /// <param name="arr"></param>
        public VComboBox(Object[] arr)
        {
            this.Items.Clear();
            for (int i = 0; i < arr.Length; i++)
            {
                if (arr[i] == null)
                {
                    this.Items.Add(DBNull.Value);
                    continue;
                }
                this.Items.Add(arr[i]);
            }
        }

        #endregion

        #region Function

       


        private void SetPopup()
        {
            popupMenu = new ContextMenuStrip();
            ContextMenuService.SetContextMenu(this, popupMenu);
            popupMenu.AddContextListener(this);

            bool isZoom = false;
            if (_lookup != null)
            {

                if ((_lookup.GetDisplayType() == DisplayType.List && ctx.GetAD_Role_ID() == 0)
                    || _lookup.GetDisplayType() != DisplayType.List)     //  only system admins can change lists, so no need to zoom for others
                {
                    popupMenu.AddZoomItem();
                    SetZoomButton();
                    isZoom = true;
                }

                popupMenu.AddRequeryItem();

            }
            if (_lookup != null && _lookup is MLookup)
            {
                //
                if (((MLookup)_lookup).GetZoomWindow() == 0 && (_field == null || _field.GetZoomWindow_ID() < 1))
                {
                    if (isZoom)
                    {
                        popupMenu.ZoomItem.IsEnabled = false;
                        zoomButton.IsEnabled = false;
                    }
                }
            }
        }

        private void SetZoomButton()
        {
            zoomButton = Envs.GetZoomButton();
            zoomButton.Click += new RoutedEventHandler(zoomButton_Click);
        }

        void zoomButton_Click(object sender, RoutedEventArgs e)
        {

            ZoomActionSearch();
            //throw new NotImplementedException();
        }
        

        public void Dispose()
        {
            VetoableChangeListener = null;

            if (worker != null)
            {
                try
                {
                    if (worker.IsBusy)
                    {
                        worker.CancelAsync();
                        //   worker = null;
                    }
                }
                catch
                {
                    // worker = null;
                }
            }
            if (worker2 != null)
            {
                try
                {
                    if (worker2.IsBusy)
                    {
                        worker2.CancelAsync();
                        //   worker = null;
                    }
                }
                catch
                {
                    // worker = null;
                }
            }

            //this.ItemsSource = null;

            if (_dataSource != null)
                _dataSource.Clear();
            _dataSource = null;

            if (popupMenu != null)
                popupMenu.Items.Clear();
            popupMenu = null;

            _field = null;
            if (_lookup != null)
                _lookup.Dispose();
            _lookup = null;

            binding = null;

        }

        #endregion

        #region Declaration
        bool _mandatory;//mendatory control status
        bool _readOnly;//read only status of control
        bool _updatable;//update status
        string _description;//discription
        string _title;//title
        private bool _inserting = false;
        protected string _columnName;//column name
        protected GridField _field;
        int _displayType;//display type of control
        Lookup _lookup;//for key pair data
        // Zoom started - requery values
        private bool zoomStarted = false;
        Classes.Context ctx = null;
        ContextMenuStrip popupMenu;
        // ToolStripMenuItem zoomItem, refreshItem, preferenceItem, bpartnerNewItem, bpartnerUpdateItem;
        private String _lastDisplay = "";
        private volatile bool _raiseEvent = true;

        private object _lastSelectedItem = null;

        protected VLogger log = null;
        private List<NamePair> _dataSource;

        BackgroundWorker worker, worker2;

        System.Windows.Data.Binding binding;
        private bool _focus = false;

        private Button zoomButton = null;



        #endregion


        #region IControl

        public event EventHandler VetoableChangeListener;

        public int GetDisplayType()
        {
            return _displayType;
        }

        public void SetDisplayType(int displayType)
        {
            _displayType = displayType;
        }

        public bool GetIsReadonly()
        {
            return _readOnly;
        }

        public void SetReadOnly(bool value)
        {

            _readOnly = value;

            if (_lookup == null && this.Items.Count == 0)
                _readOnly = true;

            SetReadOnlyState();
            //SetRectangle();
            SetBackGround(_readOnly);

            // this.IsEnabled = !_readOnly;
        }

        private void SetReadOnlyState()
        {
            //if (tgButton != null)
            //{
            //    //tgButton.IsEnabled = !_isReadOnly;
            //    VisualStateManager.GoToState(tgButton, _readOnly ? "ReadOnly" : "UndoReadOnly", true);
            //}
            VisualStateManager.GoToState(this, _readOnly ? "ReadOnly" : "UndoReadOnly", true);
        }
        // _readOnly
        //private void SetRectangle()
        //{
        //    if (readOnlyRec != null)
        //    {
        //        if (_readOnly)
        //        {
        //            readOnlyRec.Fill = new SolidColorBrush(Colors.DarkGray);
        //            readOnlyRec.Opacity = .1;
        //        }
        //        else
        //        {
        //            readOnlyRec.Opacity = 0;
        //        }
        //    }
        //}



        private Rectangle readOnlyRec = null;
        private ToggleButton tgButton = null;

        public override void OnApplyTemplate()
        {

            base.OnApplyTemplate();
            //tgButton = (ToggleButton)this.GetTemplateChild("DropDownToggle");
            if (((Rectangle)this.GetTemplateChild("ReadOnlyRect")) != null)
            {
                ((Rectangle)this.GetTemplateChild("ReadOnlyRect")).MouseLeftButtonDown += (s, e) =>
                    {
                        e.Handled = true;
                    };
            }
        }


        protected override void OnKeyUp(KeyEventArgs e)
        {
            base.OnKeyUp(e);
        }

        protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
        {
            base.OnMouseLeftButtonUp(e);
        }

        public Grids.GridField GetField()
        {
            return this._field;
        }

        public void SetField(Grids.GridField mField)
        {
            _field = mField;
            if (_field != null && MRole.GetDefault().IsShowPreference())
            {
                //Framework.ValuePreference.AddPreferenceMenuItem((Control)this, popupMenu);
                Framework.ValuePreference.AddPreferenceMenuItem(null, popupMenu);
            }
        }

        public string GetName()
        {
            return _columnName;
        }

        public void SetName(string name)
        {
            _columnName = name;
        }

        public string GetText()
        {
            return GetSelectedText();
        }

        public object GetValue()
        {
            if (this.SelectedValue != null)
            {
                if (this.SelectedValue.Equals(-1))
                    return null;
            }
            return this.SelectedValue;
        }

        public void SetValue(object value)
        {
            this.SelectedValue = value;
        }

        public bool GetIsMandatory()
        {
            return _mandatory;
        }

        public void SetIsMandatory(bool value)
        {
            _mandatory = value;
        }

        public void SetBackGround(bool value)
        {
            if (value)
            {
                _backGroundColor.Color = GlobalVariable.READONLY_TEXT_BACK_COLOR;
                this.Background = _backGroundColor;
                //if (readOnlyRec != null)

            }
            else
            {
                _backGroundColor.Color = GlobalVariable.NORMAL_TEXT_BACK_COLOR;
                this.Background = _backGroundColor;
                SetColor();
            }
        }


        /// <summary>
        /// Set back color
        /// </summary>
        /// 

        SolidColorBrush _backGroundColor = new SolidColorBrush(Colors.White);
        private void SetColor()
        {
            if (_mandatory && !_readOnly)
            {
                if (this.SelectedItem == null)
                {
                    _backGroundColor.Color = GlobalVariable.MANDATORY_TEXT_BACK_COLOR;
                    this.Background = _backGroundColor;
                    //if (readOnlyRec != null)
                    //{
                    //    readOnlyRec.Fill = new SolidColorBrush(Colors.Red);
                    //    readOnlyRec.Opacity = .1;
                    //}
                }
                else
                {
                    _backGroundColor.Color = GlobalVariable.NORMAL_TEXT_BACK_COLOR;
                    this.Background = _backGroundColor;
                    if (_field != null)
                    {
                        _field.SetError(false);
                    }
                }
            }
        }

        public string GetSelectedText()
        {
            if (SelectedItem != null && this.SelectedItem is NamePair)
            {
                return ((NamePair)this.SelectedItem).GetName();
            }
            return null;
            //throw new NotImplementedException();
        }

        public bool IsDisabled()
        {
            return !this.IsEnabled;
        }

        public void SetDisabled(bool disabled)
        {
            this.IsEnabled = !disabled;
        }

        public int GetTabIndex()
        {
            return this.TabIndex;
        }

        public void SetTabindex(int tabindex)
        {
            this.TabIndex = tabindex;
        }

        public bool Multiline
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public bool Visible
        {
            get
            {
                return this.Visibility == System.Windows.Visibility.Visible;
            }
            set
            {
                this.Visibility = value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
                if (zoomButton != null)
                {
                    zoomButton.Visibility = value ? System.Windows.Visibility.Visible : System.Windows.Visibility.Collapsed;
                }
            }
        }

        public bool Focused
        {
            get { return _focus; }
        }

        #endregion

        #region "IContextMenuListener
        public void OnMenu(ContextMenuEvent evt)
        {
            if (evt.GetContextEvent() == ContextMenuStrip.ZOOM_EVENT)
            {
                ZoomActionSearch();
            }

            else if (evt.GetContextEvent() == ContextMenuStrip.REQUERY_EVENT)
            {
                if (_lookup == null)
                    return;
                _raiseEvent = false;
                Object obj = this.SelectedItem;
                this.Cursor = Cursors.Wait;

                BackgroundWorker bgw = new BackgroundWorker();

                bgw.DoWork += (sd, ed) =>
                    {
                        ((MLookup)_lookup).Refresh();
                        // fill lookup with new data from database
                        if (((MLookup)_lookup).IsValidated())
                            _lookup.FillComboBox(_mandatory, false, false, false);
                        else
                            _lookup.FillComboBox(_mandatory, true, false, false);
                    };

                bgw.RunWorkerCompleted += (sender, e) =>
                    {
                        SetDataSource(_lookup._data);
                        BindValue = _columnName.ToUpper();
                        //this.SelectedItem = obj;
                        if (obj != null)
                        {
                            if (obj is ValueNamePair)
                            {
                                this.SelectedValue = ((ValueNamePair)obj).GetValue();
                            }
                            else
                            {
                                this.SelectedValue = ((KeyNamePair)obj).GetKey();
                            }
                        }

                        _raiseEvent = true;
                        this.Cursor = Cursors.Arrow;
                    };
                bgw.RunWorkerAsync();
            }

            else if (evt.GetContextEvent() == ContextMenuStrip.PREFERENCE_EVENT)
            {
                if (MRole.GetDefault().IsShowPreference())
                {
                    // opens Value preference window
                    Framework.ValuePreference obj = Framework.ValuePreference.Start(_field, GetValue(), GetText());
                    if (obj != null)
                    {
                        obj.Show();
                    }
                }
                return;
            }


        }

        private void ZoomActionSearch()
        {
            if (_lookup == null)
                return;
            Query zoomQuery = ((MLookup)_lookup).GetZoomQuery();
            // get selected value
            Object value = GetValue();
            ZoomAction(_lookup, zoomQuery, value, _columnName);
        }
        #endregion

        volatile bool blockDropClosed = false;

        protected override void OnDropDownOpened(EventArgs e)
        {
            if (worker != null && worker.IsBusy)
            {
                //worker.CancelAsync();
                //worker = null;
                this.Cursor = Cursors.Arrow;
                return;
            }

            base.OnDropDownOpened(e);
            _lastSelectedItem = this.SelectedItem;
            if (_lookup == null || _readOnly)
            {

                return;
            }

            //this.IsEnabled = false;
            _focus = true;
            /* Check window Id if zero then combobox is process paremeter*/
            /* requery Combobox value*/
            if ((_field != null && _field.GetAD_Window_ID() > 0)|| _lookup.GetValidation().Length < 1)
            {
                if (_lookup.IsValidated() && !_lookup.HasInactive())
                {
                    List<NamePair> source = _lookup.GetDisplayValidatedList();
                    if (source != null)
                    {
                        int count = source.Count + (!_mandatory ? 1 : 0);
                        if (count != this.Items.Count)
                        {
                            // _raiseEvent = false;
                            object selValue = this.SelectedItem;

                            if (!_mandatory)
                            {
                                //if (this.Items.Count > 0)
                                //{
                                source.Insert(0, this.Items[0] as NamePair);
                                // }
                            }

                            SetDataSource(source);
                            BindValue = _columnName.ToUpper();


                            if (selValue != null)
                            {
                                if (selValue is ValueNamePair)
                                {
                                    this.SelectedValue = ((ValueNamePair)selValue).GetValue();
                                }
                                else
                                {
                                    this.SelectedValue = ((KeyNamePair)selValue).GetKey();
                                }
                            }
                            // this.SelectedItem = selValue;

                            if (this.SelectedItem != null)
                            {
                                if (_field != null)
                                {
                                    //clear eror meassage 
                                    _field.SetError(false);
                                }
                            }

                            _raiseEvent = true;
                        }
                    }
                    // this.IsEnabled = true;
                    return;
                }
            }
            _raiseEvent = false;

            object value = this.SelectedItem;


            this.SelectedItem = null;

            blockDropClosed = true;
            worker = new BackgroundWorker();
            worker.WorkerSupportsCancellation = true;

            worker.DoWork += (sender, ev) =>
                {
                    if (worker.CancellationPending)
                    {
                        ev.Cancel = true;
                    }
                    try
                    {
                        _lookup.FillComboBox(_mandatory, true, true, true);
                    }
                    catch
                    {
                        if (worker.CancellationPending)
                        {
                            ev.Cancel = true;
                        }
                    }
                };
            worker.RunWorkerCompleted += (sender, ev) =>
            {

                //this.IsEnabled = true; ;

                if (ev.Cancelled)
                {
                    return;
                }

                SetDataSource(_lookup._data);
                // this.DisplayMemberPath = "Name";// columnName + "_d";
                // this.ValueMemberPath = "Key";
                //if (value != null)
                //{
                //    this.SelectedItem = value;
                //}
                //else
                //{
                //    this.SelectedIndex = -1;
                //}

                if (value != null)
                {

                    if(_lookup._data.Contains(value))
                    {
                        if (value is ValueNamePair)
                        {
                            this.SelectedValue = ((ValueNamePair)value).GetValue();
                        }
                        else
                        {
                            this.SelectedValue = ((KeyNamePair)value).GetKey();
                        }
                    }
                }


                if (this.SelectedItem != null)
                {
                    if (_field != null)
                    {
                        //clear eror meassage 
                        _field.SetError(false);
                    }
                }

                blockDropClosed = false;
                worker = null;
                _raiseEvent = true;
                //blockLostFocus = false;
                BindValue = this._columnName.ToUpper();
                this.Cursor = Cursors.Arrow;
            };
            worker.RunWorkerAsync();
            this.Cursor = Cursors.Wait;

        }

        ChildWindow child = new ChildWindow();


        protected override void OnDropDownClosed(EventArgs e)
        {

            base.OnDropDownClosed(e);
        }

        protected override void OnGotFocus(RoutedEventArgs e)
        {
            _focus = true;
            base.OnGotFocus(e);
        }

        protected override void OnLostFocus(RoutedEventArgs e)
        {
            base.OnLostFocus(e);
            if (!IsDropDownOpen)
                _focus = false;

        }

        public String BindValue
        {
            set
            {
                if (IsEditingControl)
                {
                    return;
                }
                binding = null;
                binding = new Binding(value);
                binding.Mode = BindingMode.TwoWay;
                this.SetBinding(VComboBox.SelectedValueProperty, binding);
            }
        }

        public bool IsEditingControl
        {
            get;
            set;
        }


        #region  "ContextMenu Function"

        /// <summary>
        /// Opens window through zoom
        /// </summary>
        /// <param name="lookup">lookup</param>
        /// <param name="zoomQuery">query</param>
        /// <param name="value">selected value</param>
        /// <param name="columnName">column name</param>
        public void ZoomAction(Lookup lookup, Query zoomQuery, Object value, String columnName)
        {


            if (lookup == null)
                return;
            if (value == null || value.ToString().Trim() == "" || value.ToString() == "-1")
                value = this.SelectedItem;

            this.Cursor = Cursors.Wait;
            if (zoomButton != null)
            {
                zoomButton.IsEnabled = false;
            }
            int AD_Window_ID = 0;

            BackgroundWorker bgw = new BackgroundWorker();
            bgw.DoWork += (sender, e) =>
                {
                    if (zoomQuery == null || (value != null))
                    {
                        zoomQuery = new Query();	//	ColumnName might be changed in MTab.validateQuery

                        string keyColumnName = null;
                        //	Check if it is a Table Reference
                        if (lookup != null && lookup is MLookup)
                        {
                            // get reference id
                            int AD_Reference_ID = ((MLookup)lookup).GetAD_Reference_Value_ID();
                            if (AD_Reference_ID != 0)
                            {
                                string query = "SELECT kc.ColumnName"
                                    + " FROM AD_Ref_Table rt"
                                    + " INNER JOIN AD_Column kc ON (rt.Column_Key_ID=kc.AD_Column_ID)"
                                    + "WHERE rt.AD_Reference_ID=" + AD_Reference_ID;
                                IDataReader dr = null;
                                try
                                {
                                    dr = DataBase.DB.ExecuteReader(query);
                                    if (dr.Read())
                                    {
                                        keyColumnName = dr["ColumnName"].ToString();
                                    }
                                    dr.Close();
                                    dr = null;
                                }
                                catch (Exception ex)
                                {
                                    if (dr != null)
                                    {
                                        dr.Close();
                                        dr = null;
                                    }
                                    // fill error log in case of any error occured
                                    log.Log(Level.SEVERE, ex.Message);
                                }
                            }
                        }
                        // Add where clause in query
                        if (keyColumnName != null && keyColumnName.Length != 0)
                            zoomQuery.AddRestriction(keyColumnName, Query.EQUAL, value);
                        else
                            zoomQuery.AddRestriction(columnName, Query.EQUAL, value);
                        // set record count of query=1
                        zoomQuery.SetRecordCount(1);
                    }
                    if (_field.GetZoomWindow_ID() > 0)
                    {
                        AD_Window_ID = _field.GetZoomWindow_ID();
                    }
                    else
                    {
                        AD_Window_ID = ((MLookup)lookup).GetZoomWindow(zoomQuery);
                    }

                };
            bgw.RunWorkerCompleted += (sc, ec) =>
                {
                    // get window id of window to be opened
                    //log.Info(columnName + " - AD_Window_ID=" + AD_Window_ID + " - Query=" + zoomQuery + " - Value=" + value);
                    
                    Apps.AWindow frame = new Apps.AWindow();
                    if (!frame.InitWindow(AD_Window_ID, zoomQuery))
                    {
                        /*sraval: sourceforge bug 1763808: commented section below to eliminate duplicate error messages in case user role does now have access to zoom to destination window
                        setCursor(Cursor.getDefaultCursor());
                        ValueNamePair pp = CLogger.retrieveError();
                        String msg = pp==null ? "AccessTableNoView" : pp.getValue();			
                        ADialog.error(m_lookup.getWindowNo(), this, msg, pp==null ? "" : pp.getName());
                        */
                    }
                    else
                    {
                        //frame.StartPosition = FormStartPosition.CenterScreen;
                        //AEnv.showCenterScreen(frame);
                        // frame.Show();
                    }
                    frame = null;
                    this.Cursor = Cursors.Arrow;
                    if (zoomButton != null)
                    {
                        zoomButton.IsEnabled = true;
                    }
                    bgw = null;
                };

            bgw.RunWorkerAsync();
            zoomStarted = true;
        }

        #endregion

        /// <summary>
        /// Create Optional User Search Lookup
        /// </summary>
        /// <param name="windowNo">window</param>
        /// <returns>VComboBox</returns>
        public static VComboBox CreateUser(int windowNo)
        {
            VComboBox cmb = new VComboBox();
            int AD_Column_ID = 10443;    //  AD_WF_Activity.AD_User_UD
            try
            {
                ThreadPool.QueueUserWorkItem(delegate
                {
                    Lookup lookup = MLookupFactory.Get(Envs.GetContext(), windowNo,
                        AD_Column_ID, DisplayType.Search);
                    System.Windows.Deployment.Current.Dispatcher.BeginInvoke(delegate
                    {
                        cmb = new VComboBox("AD_User_ID", false, false, true, lookup, 50);
                    });
                });
                return cmb;
            }
            catch (Exception e)
            {
               // log.log(Level.SEVERE, "", e);
            }
            return null;
        }

        internal Button GetzoomButton()
        {
            return zoomButton;
        }
    }
}
